//=====================================================================================
/** \file biketimer.cpp
 *    This file contains a program which will hopefully someday make a timer work on 
 *    an ME405 board with an ATmega128. This comment should be more detailed when a
 *    complete program is here. It is the student's responsibility to put something
 *    sensible here. Turning in code with this nonsense for a comment would be bad. 
 *    Roses are red, violets are blue; this comment is dumb, so fix it soon please. 
 *
 *  Revisions
 *    \li 01-05-2008 JRR Original file
 *    \li 01-04-2009 JRR Upgraded to use latest versions of base classes
 *    \li 03-30-2008 JRR Another upgrade to latest versions
 *    \li 01-04-2011 THC Edited to work with ME405 Board
 *    \li 03-29-2011 THC Edited to work with Atmega32
 *    \li 01-02-2012 JRR Tested on ME405 board with ATmega1281
 *    \Li 03-29-2012 THC Edited to work with Atmega328p
 *    \li 01-??-20?? ??? Whoever did this assignment NEEDS TO CHANGE THIS COMMENT
 * 
 *  License
 *    This file copyright 2007-2012 by JR Ridgely. It is released under the Lesser GNU
 *    public license, version 2. It is intended for educational use only, but the
 *    user is free to use it for any purpose permissible under the LGPL. The author
 *    has no control over the use of this file and cannot take any responsibility
 *    for any consequences of this use. 
 */
//=====================================================================================

											// System headers included with < >
#include <stdlib.h>							// Standard C library
#include <avr/io.h>							// Input-output ports, special registers
#include <avr/interrupt.h>					// Interrupt handling functions

											// User written headers included with " "
#include "rs232int.h"						// Serial port header
#include "stl_timer.h"						// Microsecond-resolution (approx.) timer


//-------------------------------------------------------------------------------------
/** The main function is the "entry point" of every C program, the one which runs first
 *  (after standard setup code has finished). For mechatronics programs, main() creates
 *  a bunch of objects, sets them up, then runs an infinite loop and never exits.
 *  @return Although a mechatronics program never returns (there's no OS to return to),
 *          we generally have to return something, say 0, to keep the compiler happy.
 */

int main ()
{
	volatile uint32_t dummy = 0;		// Delay loop counters should be volatile
	char input_char;					// A character typed by the user

	// Create a serial port object. The time will be printed to this port, which should
	// be hooked via USB to a dumb terminal program like GTKterm or Minicom or PuTTY
	rs232 the_serial_port (9600, 0);
	the_serial_port << clrscr << "ME405 Board is Running" << endl;

	// Create a time stamp object. This is a data structure which holds measured times
	time_stamp the_time;

	// Create another time stamp, and fill it with a time reading of zero
	time_stamp zero_time (0L);

	// Create a task timer object. Though normally used to time tasks, this timer can
	// also be used just to keep track of the time
	task_timer the_timer;

	// Print a greeting message. This is almost always a good thing because it lets 
	// the user know that the program is actually running
	the_serial_port << endl << "AVR Timer(not yet) V0.01" << endl;

	// Enable interrupts. This is necessary because the timer uses a timer interrupt
	sei ();

	// Configure Port B pin 2 as an input with its pullup resistor turned on.
	// Configure Port B pin 0 & 1 as outputs and drive them low (i.e. off)
	// DDRC is the data direction register, and PORTC is the output register,
	// If the pin is set up as an input the corresponding PORTC bit enables 
	// the pullup resistor (AVR's have no PUCRx). See the AtmegaXXX datasheet.
	DDRB  &= ~0b00000100;
	DDRB  |=  0b00000011;
	PORTB |=  0b00000101;

	// Run the main scheduling loop, in which the action to run is done repeatedly.
	// In the future, we'll run tasks here; for now, just do things in a simple loop
	while (true)
	{
		// Check if the user has typed something.
		if (the_serial_port.check_for_char ())
		{
			input_char = the_serial_port.getchar ();

			// If it's a 'c', clear the counter to a reading of zero; 
			if (input_char == 'c')
			{
				the_timer.set_time (zero_time);
				the_serial_port << endl << "Clearing timer" << endl;
			}
			// Turn on Green LED at PB1 by driving PC2 High
			else if (input_char == 'o')
			{
				PORTB &= ~0b00000001;		// Clear PC0 without clobbering the port
				PORTB |=  0b00000010;		// Set PC1 without clobbering the port
				the_serial_port << endl << "LED On" << endl;
			}
			// Turn on Red LED at PB0 by driving PC1 High
			else if (input_char == 'f')
			{
			  	PORTB &= ~0b00000010;		// Clear PC1 without clobbering the port
				PORTB |=  0b00000001;		// Set PC0 without clobbering the port
				the_serial_port << endl << "LED Off" << endl;
			}
			// If not a c,o, or f show that the program is confused
			else
			{
				the_serial_port << "?" << endl;
			}
		}

		// The dummy counter is used to slow down the rate at which stuff is printed
		// on the terminal
		if (++dummy >= 240000)
		{
			dummy = 0;

			// Check I/O port B pin 2. To read pins, one must read PINC, as PORTC is
			// the name of the output register, not the input from the pins
			if (PINB & 0b00000100)
				the_serial_port << "[1] ";
			else
				the_serial_port << "[0] ";
	
			// Print the current time, then a carriage return with no linefeed 
			the_serial_port << the_timer.get_time_now () << "\r";
		}
	}

	return (0);
}
